package com.bolingcavalry.crm.message.service.impl;/*
 * @Auther:Sadie
 * @Date:2025/8/1
 * @Description:
 * @VERSON:1.8
 */

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.base.PageResult;
import com.base.ResponseResult;
import com.base.RoleEnum;
import com.base.Status;
import com.bolingcavalry.crm.aftersales.mapper.AfterSalesMapper;
import com.bolingcavalry.crm.message.config.RabbitMQConstants;
import com.bolingcavalry.crm.message.mapper.MessageMapper;
import com.bolingcavalry.crm.message.service.MessageService;
import com.bolingcavalry.crm.security.utils.SecurityUtils;
import com.bolingcavalry.crm.servicedetails.service.ServiceDetailsService;
import com.bolingcavalry.crm.serviceorder.mapper.ServiceOrderMapper;
import com.bolingcavalry.crm.summaryorder.mapper.ServiceSummaryOrderMapper;
import com.bolingcavalry.crm.taskorder.mapper.ConfirmationMapper;
import com.bolingcavalry.crm.taskorder.mapper.TaskorderMapper;
import com.bolingcavalry.crm.user.service.UserService;
import com.bolingcavalry.crm.utils.AUtils;
import com.dto.MessageCreateDTO;
import com.dto.TaskReviewMessageDTO;
import com.dto.user.UserDTO;
import com.entity.aftersales.AfterSales;
import com.entity.message.Message;
import com.entity.summaryorder.ServiceSummaryOrder;
import com.vo.MessageVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MessageServiceImpl implements MessageService {
    @Autowired
    private MessageMapper messageMapper;
    @Autowired
    private AUtils aUtils;
    @Autowired
    private TaskorderMapper taskorderMapper;
    @Autowired
    private AfterSalesMapper afterSalesMapper;
    @Autowired
    private ServiceSummaryOrderMapper serviceSummaryOrderMapper;
    @Autowired
    private ConfirmationMapper confirmationMapper;
    @Autowired
    private ServiceOrderMapper serviceOrderMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private UserService userService;
    @Autowired
    private ServiceDetailsService serviceDetailsService;
    @Override
    public Message createMessage(MessageCreateDTO dto) {
        Message message = new Message();
        BeanUtils.copyProperties(dto, message);
        message.setCreateTime(LocalDateTime.now());
        message.setUpdateTime(LocalDateTime.now());
        if(messageMapper.insert(message)==0){
            log.info("订单号: {} 生成待办消息失败", dto.getOrderNumber());
            throw new RuntimeException("订单号: " + dto.getOrderNumber() + " 插入待办消息失败");
        }
        log.info("订单号: {} 插入待办消息成功", dto.getOrderNumber());
        return message;
    }

    //分页查询
    @Override
    public IPage<MessageVO> getMessageListByPage(Integer pageNum, Integer pageSize, String status, String content, String messageType) {
        // 1. 构建查询条件（不带权限）
        LambdaQueryWrapper<Message> queryWrapper = new LambdaQueryWrapper<>();

        // 状态多值查询
        if (status != null && !status.trim().isEmpty()) {
            List<String> statusList = Arrays.stream(status.trim().split(","))
                    .map(String::trim)
                    .filter(s -> !s.isEmpty())
                    .collect(Collectors.toList());
            queryWrapper.in(Message::getStatus, statusList);
        }
        // 消息类型匹配
        if (messageType!=null && !messageType.isEmpty()){
            queryWrapper.eq(Message::getMessageType, messageType);
        }
        // 内容模糊查询
        if (content != null && !content.isEmpty()) {
            queryWrapper.like(Message::getContent, content);
        }

        // 排序
        queryWrapper.orderByDesc(Message::getUpdateTime)
                .orderByDesc(Message::getCreateTime);

        // 2. 获取当前用户信息
        String currentUsername = SecurityUtils.getCurrentUsername();
        Long currentUserId = aUtils.getUserIdByUserName(currentUsername);
        List<String> currentUserRoles = SecurityUtils.getCurrentUserRoles();

        List<Long> currentUserRoleIds = currentUserRoles.stream()
                .map(aUtils::getRoleIdByRoleName)
                .filter(Objects::nonNull)
                .toList();

        // 3. 查询所有符合条件的数据（不分页，先查全量或大页）
        // 注意：这里不能分页查，否则会漏掉权限过滤的数据
        Page<Message> dbPage = new Page<>(1, 100000); // 查最多10万条
        IPage<Message> messageIPage = messageMapper.selectPage(dbPage, queryWrapper);

        // 4. 在内存中进行权限过滤 → 得到当前用户能看到的所有消息
        List<Message> filteredMessages = messageIPage.getRecords().stream()
                .filter(message -> {
                    if ("admin".equals(currentUsername)) return true;
                    if (message.getReceiverId() != null) {
                        return message.getReceiverId().equals(currentUserId);
                    }
                    if (message.getRoleId() != null) {
                        return currentUserRoleIds.contains(message.getRoleId());
                    }
                    return true;
                })
                .collect(Collectors.toList());

        // ✅ filteredMessages.size() 就是权限后的 total！

        // 5. 手动分页（从 filteredMessages 中切片）
        int actualPageSize = pageSize == null ? filteredMessages.size() : pageSize;
        int start = (pageNum - 1) * actualPageSize;
        int end = Math.min(start + actualPageSize, filteredMessages.size());

        // 如果起始位置超出范围，返回空
        if (start >= filteredMessages.size()) {
            start = Math.max(0, (filteredMessages.size() / actualPageSize)) * actualPageSize;
            end = Math.min(start + actualPageSize, filteredMessages.size());
        }

        List<Message> pagedMessages = filteredMessages.subList(start, end);

        // 6. VO 转换
        List<MessageVO> voList = pagedMessages.stream()
                .map(message -> {
                    MessageVO vo = new MessageVO();
                    BeanUtils.copyProperties(message, vo);
                    return vo;
                })
                .collect(Collectors.toList());

        // 7. 构造 IPage<MessageVO> 返回
        Page<MessageVO> resultPage = new Page<>();
        resultPage.setCurrent(pageNum);
        resultPage.setSize(actualPageSize);
        resultPage.setTotal(filteredMessages.size()); // ✅ 关键：权限过滤后的总数
        resultPage.setRecords(voList);
        resultPage.setPages((int) Math.ceil((double) filteredMessages.size() / actualPageSize));

        return resultPage;
    }

    @Override
    @Transactional
    public ResponseResult updateStatus(MessageCreateDTO dto) {//待处理问题
        Long id = dto.getId();
        String status = dto.getStatus();
        LambdaQueryWrapper<Message> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Message::getId, id);
        Message message = messageMapper.selectOne(queryWrapper);
        if(message==null){
            return ResponseResult.error("待办消息不存在");
        }
        //获取当前登陆人角色列表
        List<String> currentUserRoles = SecurityUtils.getCurrentUserRoles();
        int falg = 0;
        for (String currentUserRole : currentUserRoles) {
            if(currentUserRole.equals(RoleEnum.GENERAL_COMMAND.getCode())){
                falg+=3;
            }
            if(currentUserRole.equals(RoleEnum.TECHNICAL_COMMAND.getCode())){
                falg+=3;
            }
            if(currentUserRole.equals(RoleEnum.ADMIN.getCode())){
                falg+=3;
            }
        }
        //如果处理消息为同意，则需要根据对应的订单号去查询对应的消息改变状态
        if(status.equals(Status.MESSAGE_STATUS_AGREE)){
            TaskReviewMessageDTO taskReviewMessageDTO = new TaskReviewMessageDTO();
            //业务类型（有关于什么订单的比如任务task_order)
            String businessType = message.getBusinessType();
            //消息类型
            message.getMessageType();
            //订单编号
            String orderNumber = message.getOrderNumber();
            //修改总括表同步为进行中
            LambdaQueryWrapper<AfterSales> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.eq(AfterSales::getOrderNumber,orderNumber);
            AfterSales afterSales = afterSalesMapper.selectOne(wrapper1);
            //根据对应的businessType去改变对应的状态
            switch (businessType){
                //任务单
                case "task_orders":
                    //修改任务单状态为进行中
                    taskorderMapper.updateStatusByOrderNumber(orderNumber, Status.SERVICE_ORDER_STATUS_PROCESSING);
                    afterSales.setStatus(Status.SERVICE_ORDER_STATUS_PROCESSING);
                    afterSalesMapper.updateById(afterSales);
                    //修改服务单为状态为进行中
                    serviceOrderMapper.updateStatusByOrderNumber(orderNumber, Status.SERVICE_ORDER_STATUS_PROCESSING);
                    //给对应的售后人员发送消息提示需要出行
                    //对应的关联人，作为任务订单则是对应的任务接收人id，需要接收本次消息的人
                    Long relatedId = message.getRelatedId();
                    taskReviewMessageDTO.setReceiverId(relatedId);
                    taskReviewMessageDTO.setOrderNumber(orderNumber);
                    taskReviewMessageDTO.setTitle("【任务单】" + orderNumber + "审核通过"+"请出行");
                    taskReviewMessageDTO.setContent("具体信息请参考售后服务信息表");
                    taskReviewMessageDTO.setBusinessType(Status.TASK_ORDER);
                    String routingKey = RabbitMQConstants.ROUTING_KEY_NOTIFY_COMMANDER;
                    rabbitTemplate.convertAndSend(
                            RabbitMQConstants.EXCHANGE,
                            routingKey,
                            taskReviewMessageDTO
                    );
                    //设置出行人状态为售后服务
                    UserDTO user = new UserDTO();
                    user.setId(relatedId);
                    user.setStatus(Status.USER_STATUS_ON_AFTER_SALES_TRIP);
                    userService.update(user);
                    break;
                //总结单
                case "summary_orders":
                    //处理完结逻辑可以用数字实现，比如当前未通过任何部门那就是0，然后通过综合部就会变成+1，通过技术指挥部就会+2，如果最终为数值为3了，那就可以认为通过了
                    //然后设置总括表-总结单-确认单-任务单-通知单的状态都变为完结状态
                    //例如综合指挥部通过，则修改一个标志位为+1
                    message.setPassStatus(falg);
                    messageMapper.updateById(message);
                    int falg2=0;
                    LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(Message::getOrderNumber, orderNumber)
                            .eq(Message::getBusinessType, Status.SUMMARY_ORDER);
                    for (Message message1 : messageMapper.selectList(wrapper)) {
                        falg2+=message1.getPassStatus();
                    }
                    if(falg2>=3){
                        //如果为3则说明全部通过了，修改状态为完结
                        serviceSummaryOrderMapper.updateStatusByOrderNumber(orderNumber, Status.SERVICE_ORDER_STATUS_COMPLETED);
                        //修改总括表同步为已完结
                        afterSalesMapper.updateStatusByOrderNumber(orderNumber, Status.SERVICE_ORDER_STATUS_COMPLETED);
                        //设置任务表同步为已完结
                        taskorderMapper.updateStatusByOrderNumber(orderNumber, Status.SERVICE_ORDER_STATUS_COMPLETED);
                        //设置确认单同步为已完结
                        confirmationMapper.updateStatusByOrderNumber(orderNumber, Status.SERVICE_ORDER_STATUS_COMPLETED);
                        //设置通知单同步为已完结
                        serviceOrderMapper.updateStatusByOrderNumber(orderNumber, Status.SERVICE_ORDER_STATUS_COMPLETED);
                        LambdaQueryWrapper<ServiceSummaryOrder> wrapper2 = new LambdaQueryWrapper<>();
                        wrapper2.eq(ServiceSummaryOrder::getServiceNumber, orderNumber)
                                        .eq(ServiceSummaryOrder::getIsDeleted, 1);
                        ServiceSummaryOrder serviceSummaryOrder = serviceSummaryOrderMapper.selectOne(wrapper2);
                        serviceSummaryOrder.setConfirmationStamp(aUtils.getNickNameByuserName(SecurityUtils.getCurrentUsername()) + LocalDate.now());
                        serviceSummaryOrderMapper.updateById(serviceSummaryOrder);
                        //还需要把其他的消息设置为已同意
                        LambdaQueryWrapper<Message> wrapper3 = new LambdaQueryWrapper<>();
                        wrapper3.eq(Message::getOrderNumber, orderNumber)
                                .eq(Message::getBusinessType, Status.SUMMARY_ORDER)
                                .eq(Message::getStatus, Status.MESSAGE_STATUS_UNTREATED);
                        messageMapper.update(new Message(), wrapper3);

                        //设置出行人员状态为在岗位办公
                        //UserDTO user = new UserDTO();
                        //user.setId(message.getRelatedId());
                    }
                    break;
                //确认单
                case "confirmation_orders":
                //服务单
                case "service_orders":
                default:
                    break;
            }
        }
        else if(status.equals(Status.MESSAGE_STATUS_REFUSE)){
            //如果为拒绝需要有拒绝理由，将拒绝理由创建为新消息发送给对象
            //拒绝时需要传送消息内容过来作为拒绝理由
            switch(message.getBusinessType()){
                case Status.TASK_ORDER:
                    //订单编号
                    String orderNumber = message.getOrderNumber();
                    //退回任务单状态为已发布
                    taskorderMapper.updateStatusByOrderNumber(orderNumber, Status.SERVICE_ORDER_STATUS_PUBLISHED);
                    //退回总括表同步为已发布
                    LambdaQueryWrapper<AfterSales> wrapper1 = new LambdaQueryWrapper<>();
                    wrapper1.eq(AfterSales::getOrderNumber,orderNumber);
                    AfterSales afterSales = afterSalesMapper.selectOne(wrapper1);
                    afterSales.setStatus(Status.SERVICE_ORDER_STATUS_PUBLISHED);
                    afterSalesMapper.updateById(afterSales);
                    //同时遍历查询对应的其他的消息也改变为拒绝，通过业务类型和售后编号查询
                    LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(Message::getBusinessType, message.getBusinessType())
                            .eq(Message::getOrderNumber, message.getOrderNumber())
                            .eq(Message::getStatus, Status.MESSAGE_STATUS_UNTREATED)
                            .eq(Message::getMessageType, "processing");
                    for (Message message1 : messageMapper.selectList(wrapper)) {
                        message1.setStatus(Status.MESSAGE_STATUS_REFUSE);
                        message1.setContent("处理人:"+aUtils.getNickNameByuserName(SecurityUtils.getCurrentUsername())+" 拒绝内容:"+dto.getContent()+'\n'+"原消息:"+message.getContent());
                        //设置处理人姓名
                        message1.setHandlers(aUtils.getNickNameByuserName(SecurityUtils.getCurrentUsername()));
                        messageMapper.updateById(message1);
                    }

                    //创建发送消息
                    TaskReviewMessageDTO taskReviewMessageDTO = new TaskReviewMessageDTO();
                    taskReviewMessageDTO.setOrderNumber(message.getOrderNumber());
                    taskReviewMessageDTO.setServiceProblemId(message.getServiceProblemId());
                    //如：任务单25080006被拒绝
                    taskReviewMessageDTO.setTitle(aUtils.getBusinessTypename(message.getBusinessType())+message.getOrderNumber()+"被拒绝");
                    //拒绝理由
                    taskReviewMessageDTO.setContent(dto.getContent());
                    taskReviewMessageDTO.setBusinessType(message.getBusinessType());
                    taskReviewMessageDTO.setSenderName(aUtils.getNickNameByuserName(SecurityUtils.getCurrentUsername()));
                    taskReviewMessageDTO.setReceiverId(aUtils.getUserIdByNickName(message.getSenderName()));
                    rabbitTemplate.convertAndSend(
                            RabbitMQConstants.EXCHANGE,
                            RabbitMQConstants.ROUTING_KEY_REFUSE_NOTIFY,
                            taskReviewMessageDTO
                    );

                    break;
                case Status.SUMMARY_ORDER:
                    //订单编号
                    String orderNumber1 = message.getOrderNumber();
                    //String orderNumber = message.getOrderNumber();
                    //如果为总结单拒绝，则需要退回其他单状态变为待完结（总括表、通知单、任务单、确认单、总结单）
                    serviceSummaryOrderMapper.updateStatusByOrderNumber(orderNumber1, Status.SERVICE_ORDER_STATUS_TO_BE_COMPLETED);
                    //修改总括表同步为已完结
                    afterSalesMapper.updateStatusByOrderNumber(orderNumber1, Status.SERVICE_ORDER_STATUS_TO_BE_COMPLETED);
                    //设置任务表同步为已完结
                    taskorderMapper.updateStatusByOrderNumber(orderNumber1, Status.SERVICE_ORDER_STATUS_TO_BE_COMPLETED);
                    //设置确认单同步为已完结
                    confirmationMapper.updateStatusByOrderNumber(orderNumber1, Status.SERVICE_ORDER_STATUS_TO_BE_COMPLETED);
                    //设置通知单同步为已完结
                    serviceOrderMapper.updateStatusByOrderNumber(orderNumber1, Status.SERVICE_ORDER_STATUS_TO_BE_COMPLETED);
                    //同时遍历查询对应的其他的消息也改变为拒绝，通过业务类型和售后编号查询
                    LambdaQueryWrapper<Message> messageLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    messageLambdaQueryWrapper.eq(Message::getBusinessType, message.getBusinessType())
                            .eq(Message::getOrderNumber, message.getOrderNumber())
                            .eq(Message::getStatus, Status.MESSAGE_STATUS_UNTREATED)
                            //为处理的消息
                            .eq(Message::getMessageType, "processing");
                    for (Message message1 : messageMapper.selectList(messageLambdaQueryWrapper)) {
                        message1.setStatus(Status.MESSAGE_STATUS_REFUSE);
                        message1.setContent("处理人:"+aUtils.getNickNameByuserName(SecurityUtils.getCurrentUsername())+" 拒绝内容:"+dto.getContent()+'\n'+"原消息:"+message.getContent());
                        //设置处理人姓名
                        message1.setHandlers(aUtils.getNickNameByuserName(SecurityUtils.getCurrentUsername()));
                        messageMapper.updateById(message1);
                    }

                    //创建发送消息给发送消息的人发送一条拒绝消息，通知这条被拒绝退回了前置状态
                    TaskReviewMessageDTO reviewMessageDTO = new TaskReviewMessageDTO();
                    reviewMessageDTO.setOrderNumber(message.getOrderNumber());
                    reviewMessageDTO.setServiceProblemId(message.getServiceProblemId());
                    //如：任务单25080006被拒绝
                    reviewMessageDTO.setTitle(aUtils.getBusinessTypename(message.getBusinessType())+message.getOrderNumber()+"被拒绝");
                    //拒绝理由
                    reviewMessageDTO.setContent(dto.getContent());
                    reviewMessageDTO.setBusinessType(message.getBusinessType());
                    reviewMessageDTO.setSenderName(aUtils.getNickNameByuserName(SecurityUtils.getCurrentUsername()));
                    reviewMessageDTO.setReceiverId(aUtils.getUserIdByNickName(message.getSenderName()));
                    rabbitTemplate.convertAndSend(
                            RabbitMQConstants.EXCHANGE,
                            RabbitMQConstants.ROUTING_KEY_REFUSE_NOTIFY,
                            reviewMessageDTO
                    );
                    break;
                default:
                    break;
            }
        }
        LocalDateTime processedTime = LocalDateTime.now();
        if(messageMapper.updateStatus(id, status,processedTime)==0){
            log.info("更新待办消息: {} 状态为: {} 失败", id, status);
            return ResponseResult.error("更新待办消息失败");
        }
        return ResponseResult.success("更新待办消息成功");
    }

    @Override
    public ResponseResult<MessageVO> getMessageById(Long id) {
        LambdaQueryWrapper<Message> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Message::getId, id);
        Message message = messageMapper.selectOne(wrapper);
        if(message==null){
            return ResponseResult.error("该条消息已被删除");
        }
        String messageType = message.getMessageType();
        if(messageType.equals("notices")&&message.getStatus().equals(Status.MESSAGE_STATUS_UNTREATED)){
            //如果为通知类型的消息，获取之后则变为已处理
            messageMapper.updateStatus(id, Status.MESSAGE_STATUS_PROCESSED, LocalDateTime.now());
        }
        MessageVO messageVO = new MessageVO();
        BeanUtils.copyProperties(message, messageVO);
        return ResponseResult.success(messageVO);
    }
}
